//==============================================================================
//
//          DSystemLogger - the system logger in the ofc-library
//
//               Copyright (C) 2004  Dick van Oudheusden
//  
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public
// License along with this library; if not, write to the Free
// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
//==============================================================================
// 
//  $Date: 2006-07-22 13:28:57 $ $Revision: 1.4 $
//
//==============================================================================

#include "ofc/DSystemLogger.h"

#ifdef HAVE_DSYSTEMLOGGER
#include <syslog.h>
#endif

#include "ofc/DText.h"
#include "ofc/DDateTime.h"


#if _INTERFACE_

#include "ofc/config.h"

#include "ofc/DLogger.h"

#ifdef HAVE_SYSLOG_H
#define HAVE_DSYSTEMLOGGER
#endif

#ifdef HAVE_DSYSTEMLOGGER
//
// The DSystemLogger class implements methods for continuous logging
// to the system logger. On Unix this will be the syslog deamon. On
// Win32 there is not an usable logger present. So this class will only
// be present on Unix.
// 

@interface DSystemLogger : Object <DLogger>
{
  int _mask;        // the (copy of) the mask
}
#endif
#endif

#ifdef HAVE_DSYSTEMLOGGER

@implementation DSystemLogger

  
//// Constructors

//
// Initialise a default system logger
//
// @return the object
//

- (DSystemLogger *) init
{
  [self init :NULL :NO];

  return self;
}

//
// Initialise a system logger
// 
// @param appName   the application name (or NULL)
// @param toStdErr  also logging to stderr ?
//
// @return the object
//

- (DSystemLogger *) init :(const char *) appName :(BOOL) toStdErr
{
  int options = 0;
  
  [super init];

  // Enable all log levels
  _mask = DLOG_PANIC | DLOG_ALERT   | DLOG_CRITICAL |
          DLOG_ERROR | DLOG_WARNING | DLOG_NOTICE   |
          DLOG_INFO  | DLOG_DEBUG;

  if (toStdErr)
  {
    options |= LOG_PERROR;
  }
  
  if (appName == NULL)
  {
    options |= LOG_PID;
  }
  
  openlog(appName, options, LOG_USER);
  
  return self;
}


//// Copy constructor

//
// Do a shallow copy of the object (not implemented)
//
// @return the object
//
- shallowCopy
{
  WARNING(DW_METHOD_NOT_IMPL, "shallowCopy");
  
  return [super shallowCopy];
}


//// Deconstructor

//
// Free the object
//
// @return the object
//

- free
{
  closelog();
  
  return [super free];
}


//// Implementation of interface DLogger

#if _PRIVATE_

int _log2sys(int level)
{
  int sysLevel = 0;
  
  switch (level)
  {
   case DLOG_ALERT:
    sysLevel = LOG_ALERT;   break;
    
   case DLOG_CRITICAL:
    sysLevel = LOG_CRIT;    break;
    
   case DLOG_ERROR:
    sysLevel = LOG_ERR;     break;
    
   case DLOG_WARNING:
    sysLevel = LOG_WARNING; break;
    
   case DLOG_NOTICE:
    sysLevel = LOG_NOTICE;  break;
    
   case DLOG_INFO:
    sysLevel = LOG_INFO;    break;
    
   case DLOG_DEBUG:
    sysLevel = LOG_DEBUG;   break;
    
   case DLOG_PANIC:
   default:
    sysLevel = LOG_EMERG;   break;
  }
  
  return sysLevel;
}

#endif

//
// Log an event by the logger
// 
// @param level      the level of the event
// @param message    the message to be logged
// @param parameters the optional parameters for the message
// 
// @return success
// 
- (BOOL) doLog :(int) level :(const char *) message
{
  syslog(_log2sys(level), message);
  
  return YES;
}

//
// Set the active levels
// 
// @param level      the bitwise or'ed active levels 
// 
// @return the previous mask
// 
- (int) mask :(int) levels
{
  int prev    = _mask;
  int level   = 0;
  int sysmask = 0;
  int syslvl  = 0;
  
  _mask = levels;

  for (level = DLOG_PANIC; level <= DLOG_DEBUG; level <<= 1)
  {
    if ((level & levels) != 0)
    {
      syslvl = _log2sys(level);
      
      sysmask |= LOG_MASK(syslvl);
    }
  }
  
  setlogmask(sysmask);
  
  return prev;
}

//
// Set the active level range
// 
// @param high        the highest level to mask
// @param low         the lowest level to mask
// 
// @return the previous mask
//
- (int) mask :(int) high :(int) low
{
  int prev    = _mask;
  int sysmask = 0;
  int syslvl  = 0;
  
  if (high < low)
  {
    WARNING(DW_INVALID_ARG, "low");
  }
  else
  {
    unsigned bit = low;
    
    _mask = 0;
    
    while (bit <= high)
    {
      _mask |= bit;

      syslvl = _log2sys(bit);
      
      sysmask |= LOG_MASK(syslvl);
      
      bit <<= 1;
    }
    
    setlogmask(sysmask);
  }
  
  return prev;
}

@end
#endif

/*==========================================================================*/
